package efg.library.JAAS;

import java.util.Map;
import java.util.Set;
import java.security.Principal;

import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.security.auth.Subject;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.NameCallback;
import javax.security.auth.callback.PasswordCallback;
import javax.security.auth.login.LoginException;
import javax.security.auth.spi.LoginModule;

import efg.library.IF.LibraryAdminIF;

public class LibraryLoginModule implements LoginModule {  
	private static LibraryAdminIF libraryAdmin;

	private Set<Principal> principals = null;
	private CallbackHandler callbackHandler = null;

	// the authentication status
	private boolean succeeded = false;
	private boolean commitSucceeded = false;

	// roles, callerPrincipal
	private MyGroup roles = null;
	private MyGroup callerPrincipal = null;

	public void initialize(Subject subject, CallbackHandler callbackHandler, Map<String, ?> sharedState, Map<String, ?> options) {
		principals = subject.getPrincipals();
		System.out.println("principals="+principals);
		this.callbackHandler = callbackHandler;
	}

	public boolean login() throws LoginException {
		boolean ret = false;

		NameCallback nc = new NameCallback("Username: ", "guest");
		PasswordCallback pc = new PasswordCallback("Password: ", false);
		Callback[] callbacks = new Callback[]{ nc, pc };

		try {
			callbackHandler.handle(callbacks);
		} catch(Exception e) {
			throw new LoginException(e.getMessage());
		}

		String username = nc.getName();
		String password = new String(pc.getPassword());
		pc.clearPassword();

		InitialContext ctx;
		try {
			ctx = new InitialContext();
			libraryAdmin = (LibraryAdminIF)ctx.lookup("LibraryAdminBean/local");

			String[] myroles = libraryAdmin.check(username, password);
			if (myroles != null) {  
				roles = new MyGroup("Roles");

				String rol = "";
				for (int i=0; i<myroles.length; i++) {
					roles.addMember(new MyPrincipal(myroles[i]));
					rol += myroles[i] + ", ";
				}
				callerPrincipal = new MyGroup("CallerPrincipal");
				callerPrincipal.addMember(new MyPrincipal(username));

				System.out.println("- JAAS: Permission granted for user "+username+" with password "+password+", roles: "+rol);
				ret = succeeded = true;
			}

		} catch(NamingException e) {
			System.out.println(e.getMessage());
			System.out.println("- JAAS: Access denied for user "+username+" and password "+password+"!");

		}

		return ret;
	}

	public boolean commit() {
		boolean ret = false;
		if (succeeded) {
			principals.add(roles);
			principals.add(callerPrincipal);
			ret = commitSucceeded = true;
		}
		return ret;
	}

	public boolean abort() {
		boolean ret = true;
		succeeded = false;
		if (commitSucceeded) {
			ret = ret && logout();
			commitSucceeded = false;
		}
		return ret;
	}

	public boolean logout() {
		boolean ret = principals.remove(roles);
		ret = ret && principals.remove(callerPrincipal);
		return ret;
	}
}